69장. ElastiCache (Redis) — 캐시 계층의 이해
이 장에서 말하고자 하는 것
데이터베이스로 부족한 게 하나 더 있다.
“수십 ms 가 아니라 한 자릿수 ms로 응답해야 한다”
DB는 디스크 기반이라 일정 한계가 있다.
이때 등장하는 게
인-메모리 데이터 저장소
이고 AWS의 관리형 옵션이
Amazon ElastiCache (Redis · Valkey · Memcached)
다.
대부분의 운영에서 Redis (또는 Valkey) 를 쓴다.
1. 캐시가 풀어주는 문제
같은 데이터를 자꾸 읽을 때
사용자가 매번 "내 프로필" 요청
↓
매번 DB Query → 부하 누적
캐시를 끼우면
요청 → 캐시 확인
└─ 있음 (HIT) → 즉시 응답
└─ 없음 (MISS) → DB Query → 캐시에 저장 → 응답
같은 데이터는 그 뒤로 캐시에서 바로 응답된다.
2. ElastiCache가 잘하는 다른 일들
- 세션 저장 (서버 무상태 유지)
- Rate limit 카운터 (분 단위 요청 수)
- 실시간 랭킹 / 리더보드
- Pub/Sub 메시징
- 분산 락
Redis는 단순 키-값을 넘는 다양한 자료구조를 지원한다.
String · Hash · List · Set · Sorted Set · Stream · ...
3. 클러스터 vs 단일 노드
단일 노드 (Standalone)
- Primary 1 + Replica N
- 메모리 한도 = 한 노드의 메모리
- 단순하다
Cluster Mode Enabled
- 데이터를 여러 샤드에 분산
- 메모리 한도 = N × 노드 메모리
- 클라이언트가 cluster를 인식해야 함
처음에는 단일 노드 + Replica 1~2개로 시작
데이터가 한 노드 메모리 한도에 가까워지면 Cluster Mode 검토
4. 휘발성 — 영구 저장소가 아니다
Redis는 메모리 기반이다.
- 노드 재시작 → 데이터 사라짐 가능
- AOF · 스냅샷 옵션이 있지만 RDB · DynamoDB 수준의 보존을 기대하면 안 된다
캐시는 캐시일 뿐 — 원본은 DB
캐시가 텅 비어도 (Cold start) 시스템이 살아남아야 한다.
5. 캐시 패턴
Cache-Aside (가장 흔함)
1. 캐시 확인
2. MISS → DB 조회 → 캐시에 저장 → 반환
3. HIT → 캐시에서 바로 반환
Write-Through
쓸 때 DB + 캐시 동시에
Write-Behind
캐시에만 즉시 쓰고 DB는 비동기로
(데이터 손실 위험)
운영의 80%는 Cache-Aside로 시작.
6. TTL — 데이터 유효 기간
캐시 항목마다 만료 시간을 둔다.
SET user:u-1 "..." EX 300 ← 5분 후 자동 삭제
- 너무 길게 → 옛 데이터 응답
- 너무 짧게 → DB로 자꾸 떨어짐
대부분 1분 ~ 1시간 범위에서 결정.
7. 보안 · 네트워크
- VPC 안에 둔다 (퍼블릭 노출 금지)
- 인증 (Redis AUTH 또는 IAM Auth)
- 전송 암호화 (TLS)
- 저장 암호화 (KMS)
Security Group:
인바운드: ECS Task SG에서 오는 6379
8. 우리 서비스에서
[ECS Service "orders"]
↓ 캐시 먼저 보고
[ElastiCache Redis]
↓ MISS
[RDS PostgreSQL]
- 사용자 프로필 조회 → 캐시
- 카탈로그 목록 → 캐시
- 세션 토큰 → 캐시
- Rate limit 카운터 → 캐시
DB 부하의 절반 이상이 캐시로 흡수된다.
9. 직접 확인해보기 — CLI
클러스터 만들기 (단일 노드 + Replica 1)
aws elasticache create-replication-group \
--replication-group-id orders-cache \
--replication-group-description "orders cache" \
--engine redis \
--cache-node-type cache.t4g.small \
--num-cache-clusters 2 \
--automatic-failover-enabled \
--transit-encryption-enabled \
--at-rest-encryption-enabled \
--cache-subnet-group-name private-cache \
--security-group-ids sg-cache-xxx
redis-cli 접속
redis-cli -h master.orders-cache.xxx.cache.amazonaws.com --tls
> SET user:u-1 "json" EX 300
> GET user:u-1
10. 코드로는 이렇게 생겼다 — Terraform
resource "aws_elasticache_subnet_group" "main" {
name = "private-cache"
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
}
resource "aws_elasticache_replication_group" "orders" {
replication_group_id = "orders-cache"
description = "orders cache"
engine = "redis"
node_type = "cache.t4g.small"
num_cache_clusters = 2
automatic_failover_enabled = true
subnet_group_name = aws_elasticache_subnet_group.main.name
security_group_ids = [aws_security_group.cache.id]
transit_encryption_enabled = true
at_rest_encryption_enabled = true
}
11. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. 캐시를 영구 저장소처럼 쓴다
노드 재시작에 데이터가 사라질 수 있다.
항상 원본은 DB
안티패턴 2. TTL 없이 캐시한다
오래된 데이터가 영원히 응답된다.
안티패턴 3. 캐시가 죽었을 때 시스템도 같이 죽는다
Redis 장애가 곧 서비스 장애로 전이된다.
캐시 실패 시 DB로 우회하는 경로를 코드로 보장
안티패턴 4. 캐시를 보안 없이 운영
TLS · AUTH 안 켜고 VPC 안이라 안전하다고 가정.
전송 · 저장 암호화는 거의 항상 켠다
12. 한 줄로 정리
ElastiCache는 DB 앞단에 두는 인-메모리 캐시이며,
캐시는 캐시일 뿐 — 원본은 항상 DB라는 원칙 위에 운영한다
13. 이 장의 핵심 정리
- Redis는 한 자릿수 ms 응답의 인-메모리 저장소다.
- 캐시 · 세션 · Rate limit · 랭킹 · Pub/Sub에 다양하게 쓴다.
- 휘발성이라 영구 저장소처럼 쓰지 않는다.
- Cache-Aside가 가장 흔한 패턴이다.
- TTL · 보안 · 캐시 실패 경로 설계가 운영의 출발선이다.